

'''
@time:2025.04.15

面向对象最重要的概念就是类（Class）和实例（Instance），必须牢记类是抽象的模板，
比如Student类，而实例是根据类创建出来的一个个具体的“对象”，每个对象都拥有相同的方法，但各自的数据可能不同。

'''

# 定义一个类
class Student():
    count = 0
    def __init__(self,name,age,score):  # 构造函数，实例化对象时自动调用，用来初始化实例变量，在实例化对象进，必须传入对应参数。
        Student.count += 1    # 类变量，所有实例共享，为什么直接写count += 1会错呢？ 因为count是类变量，所以需要用类名来访问，而不是实例名。
        self.name = name
        self.age = age
        self.score = score

    def print_info(self):   # 实例方法，每个实例都有自己的print_info方法，可以打印自己的信息。
        print("学生的姓名是：",self.name)
        print("学生的年龄是：",self.age)

# 实例化对象，通过类名加上()来调用构造函数，括号内传入对应参数。对应类的构造函数，会自动调用，并初始化实例变量。
stu1 = Student("bing",19,99)    # 实例化对象,需要传入对应参数，调用构造函数。
stu2 = Student("林风",20,100)
stu1.name = "bingbing"     # 实例变量，每个实例都有自己的name属性，赋值给stu1.name，不会影响stu2.name，只改变了stu1的name属性。
print(stu1.name)
print(stu2.name)
print(Student.count) # 2   为什么是2呢？ 因为stu1和stu2都是Student类的实例，所以count自增了两次
# 类变量和实例变量的区别：
# 类变量：类变量是属于类本身的变量，不属于任何一个实例，它的值在类所有实例之间共享。类变量通常用于类相关的静态数据。
# 实例变量：实例变量是属于实例本身的变量，每个实例都有自己的数据，互不干扰。实例变量用于保存对象特有的状态信息。
stu1.print_info()   # 调用实例方法，打印stu1的信息。
print(stu1.count)   # 打印stu1的count属性  为什么stu1.count打印的是2呢？ 因为count是类变量，所有实例共享，所以打印的是所有实例的count值之和。
# 可以自由的给实例变量添加属性和方法，或更改已有属性和方法的功能，  这就是面向对象编程的精髓。
stu1.gender = "男"   # 给stu1添加gender属性
print(stu1.gender)


def print_score(self):   # 给stu1添加print_score方法
    print("学生的成绩是：",self.score)
stu1.print_score = print_score   # 给stu1的实例添加print_score方法
# stu1.print_score()   # 这里为什么会错误？ 因为print_score方法没有传入self参数，所以会报错。
stu1.print_score(stu1)   # 正确的调用方式，传入self参数。需要一个实参。



class Animal:
    '''
    定义一个动物类，有动物的名字，动物的叫声。
    动物的叫声是根据动物的名字决定的，所以这里用字典来存储动物的叫声。
    '''
    cry = {'猫': '喵喵', '狗': '汪汪', '羊': '咩咩', '狼': '嗷嗷', '牛': '哞哞'} #类属性
    def __init__(self,name):   #这里是强制绑定类的实例属性，所有Animal类的实例都具有这些属性
        '''
        构造函数，实例化对象时自动调用，用来初始化实例变量，在实例化对象进，必须传入对应参数。
        :param name:
        '''
        self.name = name     # 这里是动态绑定实例属性，每个实例都有自己的name属性，互不干扰。
    def say(self):
        '''
        实例方法，每个实例都有自己的say方法，可以打印自己的信息。'''
        if self.name not in self.cry:    # 使用not in判断，判断是否在字典中，如果不在，则打印未收录。
            print('未收录')
        else:
            print(f'{self.name}:{self.cry[self.name]}')      # 打印对应的动物叫声。
sheep = Animal('羊')            # 实例化对象，传入参数，调用构造函数。
sheep.age = 2  #给这个实例对象绑定一个属性，这个属性只有sheep才有
print(f'{sheep.name}{sheep.age}岁啦！')
sheep.say()
dog = Animal('狗')
dog.say()
pig = Animal('猪')
pig.say()
